from rest_framework import serializers
import datetime, pymysql, logging, re, xlrd
from django.db.models import Count, Sum, Max, Min, Avg, Q, F
from django.db import transaction
from django.conf import settings
from random import randint

from equity_admin.filters_cashbonus import *
from equity_mall.utils.utils import get_level_list
from users.models import *
from merchants.models import *

logger = logging.getLogger('django')


class LevelListSerializer(serializers.ModelSerializer):

    class Meta:
        model = Level
        fields = ('id', 'prov_name', 'city_name', 'district_name', 'branch_name', 'orgId', 'account', 'account_nine', 'level')


class CashActivityListModelSerializer(serializers.ModelSerializer):

    activity_type_str = serializers.CharField(source='get_activity_type_display', read_only=True)
    activity_state_str = serializers.CharField(source='get_activity_state_display', read_only=True)
    rule = serializers.SerializerMethodField(read_only=True)
    activity_state = serializers.SerializerMethodField(read_only=True)
    available_begin_time = serializers.DateTimeField(format="%Y.%m.%d %H:%M:%S", required=False)
    available_end_time = serializers.DateTimeField(format="%Y.%m.%d %H:%M:%S", required=False)
    publish_time = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivity
        fields = ['id', 'name', 'activity_type', 'activity_type_str', 'activity_state', 'activity_state_str', 'max_amount', 'remain_amount', 'available_begin_time', 'available_end_time', 'rule', 'publish_time',
                  'level_name']

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_publish_time(self, obj):
        try:
            return f'{obj.available_begin_time.strftime("%Y.%m.%d %H:%M:%S")}-{obj.available_end_time.strftime("%Y.%m.%d %H:%M:%S")}'
        except:
            return ''

    def get_activity_state(self, obj):
        try:
            now_date = datetime.datetime.now()
            if obj.activity_state != 4 and obj.available_end_time < now_date:
                obj.activity_state = 4
                obj.save()
                return 4
            return obj.activity_state
        except:
            return obj.activity_state

    def get_rule(self, obj):
        try:
            if obj.activity_type in [1, 4, 8]:
                return f'{obj.min_distributed_amount}-{obj.max_distributed_amount}'
            else:
                cashactivityrule_set = obj.cashactivityrule_set.filter(is_delete=0).order_by('amount')
                result = ''
                for cashactivityrule in cashactivityrule_set:
                    result += f'{cashactivityrule.amount},'
                return result[:-1]
        except:
            return ''


class CashActivityRuleModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = CashActivityRule
        fields = ['id', 'amount', 'probability']


class CashActivityRetrieveModelSerializer(serializers.ModelSerializer):

    activity_type_str = serializers.CharField(source='get_activity_type_display', read_only=True)
    activity_state_str = serializers.CharField(source='get_activity_state_display', read_only=True)
    is_check_identity_str = serializers.CharField(source='get_is_check_identity_display', read_only=True)
    rule = serializers.SerializerMethodField(read_only=True)
    available_begin_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    available_end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    level = serializers.SerializerMethodField(read_only=True)
    can_remain_amount = serializers.SerializerMethodField(read_only=True)
    cashactivityrule_set = CashActivityRuleModelSerializer(many=True)
    developer_set = serializers.SerializerMethodField(read_only=True)
    id = serializers.SerializerMethodField(read_only=True)
    wx_channel = serializers.SerializerMethodField(read_only=True)
    ali_channel = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivity
        fields = ['id', 'name', 'activity_type', 'activity_type_str', 'activity_state', 'activity_state_str', 'max_amount', 'remain_amount', 'available_begin_time', 'available_end_time', 'rule',
                  'activity_description', 'create_time', 'level', 'can_remain_amount', 'is_max_amount_by_day', 'is_max_amount_by_user_by_day', 'is_max_amount_by_user',
                  'is_max_amount_by_customeruser', 'max_amount_by_day', 'max_amount_by_user_by_day', 'max_amount_by_user', 'max_amount_by_customeruser', 'cashactivityrule_set',
                  'is_need_auth', 'is_check_identity', 'is_check_identity_str', 'developer_set', 'wx_channel', 'ali_channel', 'wx_channel_id', 'ali_channel_id',
                  'is_push_ylx', 'is_psbc_card', 'is_wechat', 'is_white', 'is_limit_white', 'white_accout', 'is_merchant', 'repeat_business_no_count',
                  'is_keguan', 'pushEventIds', 'is_white_merchant']

    def get_ali_channel(self, obj):
        try:
            return f'{obj.ali_channel.name}({obj.ali_channel.mchid})'
        except:
            return ''

    def get_wx_channel(self, obj):
        try:
            return f'{obj.wx_channel.name}({obj.wx_channel.mchid})'
        except:
            return ''

    def get_id(self, obj):
        try:
            return obj.activity_id
        except:
            return ''

    def get_developer_set(self, obj):
        data = []
        try:
            developer_set = CashActivityAPIRelation.objects.filter(cashactivity_id=obj.id)
            for developer in developer_set:
                user = developer.developer
                data.append({
                    'id': developer.id,
                    'account': user.account,
                    'nickname': user.nickname
                })
        except:
            pass
        return data

    def get_can_remain_amount(self, obj):
        try:
            max_amount__sum = obj.cashactivitylevel_set.all().aggregate(Sum('max_amount'))['max_amount__sum']
            if max_amount__sum:
                remain_amount = obj.max_amount - max_amount__sum
            else:
                remain_amount = obj.max_amount
            return remain_amount
        except:
            return 0

    def get_rule(self, obj):
        try:
            if obj.activity_type in [1, 4, 8]:
                return f'{obj.min_distributed_amount}-{obj.max_distributed_amount}'
            else:
                cashactivityrule_set = obj.cashactivityrule_set.filter(is_delete=0).order_by('amount')
                result = ''
                for cashactivityrule in cashactivityrule_set:
                    result += f'{cashactivityrule.amount},'
                return result[:-1]
        except:
            return ''

    def get_level(self, obj):
        data = {
            'prov_name': '',
            'city_name': '',
            'district_name': '',
            'branch_name': '',
            'account': ''
        }
        try:
            level = obj.level
            data['prov_name'] = level.prov_name
            data['city_name'] = level.city_name
            data['district_name'] = level.district_name
            data['branch_name'] = level.branch_name
            data['account'] = level.account
            return data
        except:
            return data


class CashActivityLevelListModelSerializer(serializers.ModelSerializer):

    level_type = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    p_unclaimed_amount = serializers.SerializerMethodField(read_only=True)
    activity_name = serializers.SerializerMethodField(read_only=True)
    is_auth_str = serializers.CharField(source='get_is_auth_display', read_only=True)

    class Meta:
        model = CashActivityLevel
        fields = ['id', 'level_type', 'level_name', 'remain_amount', 'activity_name',
                  'p_receive_amount', 'p_remain_amount', 'p_take_amount', 'p_max_amount', 'p_unclaimed_amount', 'is_auth', 'is_auth_str']

    def get_p_unclaimed_amount(self, obj):
        try:
            p_unclaimed_amount = obj.p_take_amount - obj.p_receive_amount
            return p_unclaimed_amount
        except:
            return ''

    def get_activity_name(self, obj):
        try:
            return obj.cash_activity.name
        except:
            return ''

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_level_type(self, obj):
        try:
            level = obj.level.level
            if level == 1:
                return '省公司'
            elif level == 2:
                return '市公司'
            elif level == 3:
                return '区县'
            elif level == 4:
                return '网点'
            else:
                return '信翔'
        except:
            return ''


class CashActivityLevelRetrieveModelSerializer(serializers.ModelSerializer):

    level_type = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    unclaimed_amount = serializers.SerializerMethodField(read_only=True)
    activity_name = serializers.SerializerMethodField(read_only=True)
    can_amount = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivityLevel
        fields = ['id', 'level_type', 'level_name', 'max_amount', 'take_amount', 'remain_amount', 'unclaimed_amount', 'receive_amount', 'activity_name', 'can_amount']

    def get_can_amount(self, obj):
        data = {}
        data['max_amount'] = 0
        data['min_amount'] = 0
        try:
            cash_activity = obj.cash_activity
            max_amount__sum = cash_activity.cashactivitylevel_set.all().aggregate(Sum('max_amount'))['max_amount__sum']
            if max_amount__sum:
                remain_amount = cash_activity.max_amount - max_amount__sum
            else:
                remain_amount = cash_activity.max_amount
            data['max_amount'] = obj.max_amount + remain_amount
            data['min_amount'] = obj.max_amount - obj.remain_amount
        except:
            pass
        return data

    def get_unclaimed_amount(self, obj):
        try:
            unclaimed_amount = obj.take_amount - obj.receive_amount
            return unclaimed_amount
        except:
            return ''

    def get_activity_name(self, obj):
        try:
            return obj.cash_activity.name
        except:
            return ''

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_level_type(self, obj):
        try:
            level = obj.level.level
            if level == 1:
                return '省公司'
            elif level == 2:
                return '市公司'
            elif level == 3:
                return '区县'
            elif level == 4:
                return '网点'
            else:
                return '信翔'
        except:
            return ''


class CashActivityDataListModelSerializer(serializers.ModelSerializer):

    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    received_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    state_str = serializers.CharField(source='get_state_display', read_only=True)
    customeruser_realname = serializers.SerializerMethodField(read_only=True)
    companyuser_nickname = serializers.SerializerMethodField(read_only=True)
    activity_name = serializers.SerializerMethodField(read_only=True)
    activity_type = serializers.SerializerMethodField(read_only=True)
    activity_type_str = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    city_name = serializers.SerializerMethodField(read_only=True)
    district_name = serializers.SerializerMethodField(read_only=True)
    mobile = serializers.SerializerMethodField(read_only=True)
    merchant = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivityData
        fields = ['id', 'create_time', 'mobile', 'state', 'state_str', 'received_time', 'customeruser_realname', 'companyuser_nickname', 'activity_name',
                  'activity_type', 'activity_type_str', 'level_name', 'amount', 'city_name', 'district_name', 'merchant']

    def get_merchant(self, obj):
        data = {}
        data['business_no'] = ''
        data['merchant_name'] = ''
        data['level_name'] = ''
        data['is_white'] = ''
        try:
            white = CashActivityDataWhiteTable.objects.filter(activitydata_id=obj.id).first()
            if white:
                data['business_no'] = white.business_no
                data['is_white'] = str(white.is_white_table)
                if white.is_white_table == 0:
                    merchant = Merchant.objects.filter(wyfMerchantID=white.business_no).first()
                    data['merchant_name'] = merchant.name
                    data['level_name'] = merchant.level.name
        except:
            pass
        return data

    def get_city_name(self, obj):
        try:
            return obj.level.city_name
        except:
            return ''

    def get_district_name(self, obj):
        try:
            return obj.level.district_name
        except:
            return ''

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_activity_type_str(self, obj):
        try:
            return obj.cash_activity.get_activity_type_display()
        except:
            return ''

    def get_activity_type(self, obj):
        try:
            return obj.cash_activity.activity_type
        except:
            return ''

    def get_activity_name(self, obj):
        try:
            return obj.cash_activity.name
        except:
            return ''

    def get_customeruser_realname(self, obj):
        try:
            return obj.customer_user.realname
        except:
            return ''

    def get_mobile(self, obj):
        try:
            if obj.customer_user:
                return obj.customer_user.mobile
            elif obj.customeruservice:
                return obj.customeruservice.mobile
            else:
                return obj.mobile
        except:
            return ''

    def get_companyuser_nickname(self, obj):
        try:
            return obj.companyuser.nickname
        except:
            return ''


class CashActivityDataRetrieveModelSerializer(serializers.ModelSerializer):

    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    received_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    expired_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    state_str = serializers.CharField(source='get_state_display', read_only=True)
    customeruser_realname = serializers.SerializerMethodField(read_only=True)
    companyuser_nickname = serializers.SerializerMethodField(read_only=True)
    activity_name = serializers.SerializerMethodField(read_only=True)
    activity_type = serializers.SerializerMethodField(read_only=True)
    activity_type_str = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    mobile = serializers.SerializerMethodField(read_only=True)
    mchid = serializers.SerializerMethodField(read_only=True)
    city_name = serializers.SerializerMethodField(read_only=True)
    district_name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivityData
        fields = ['id', 'create_time', 'mobile', 'state', 'state_str', 'received_time', 'customeruser_realname', 'companyuser_nickname', 'activity_name',
                  'activity_type', 'activity_type_str', 'level_name', 'amount', 'expired_time', 'payment_no', 'cash_activity_id', 'return_msg', 'mchid', 'payeeFullName',
                  'city_name', 'district_name']

    def get_city_name(self, obj):
        try:
            return obj.level.city_name
        except:
            return ''

    def get_district_name(self, obj):
        try:
            return obj.level.district_name
        except:
            return ''

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_mchid(self, obj):
        try:
            channel = obj.channel
            if channel:
                return f'{channel.name}({channel.mchid})'
            else:
                return ''
            # if obj.mchid == '1486198522':
            #     return '信翔商户(1486198522)'
            # elif obj.mchid == '1571060401':
            #     return '信亨商户(1571060401)'
            # elif obj.mchid == 'wx':
            #     return '信翔商户(1486198522)'
            # elif obj.mchid == 'alipay':
            #     return '信翔支付宝服务商(2088631976752358)'
            # else:
            #     return ''
        except:
            return ''

    def get_activity_type_str(self, obj):
        try:
            return obj.cash_activity.get_activity_type_display()
        except:
            return ''

    def get_activity_type(self, obj):
        try:
            return obj.cash_activity.activity_type
        except:
            return ''

    def get_activity_name(self, obj):
        try:
            return obj.cash_activity.name
        except:
            return ''

    def get_customeruser_realname(self, obj):
        try:
            return obj.customer_user.realname
        except:
            return ''

    def get_mobile(self, obj):
        try:
            if obj.customer_user:
                return obj.customer_user.mobile
            elif obj.customeruservice:
                return obj.customeruservice.mobile
            else:
                return obj.mobile
        except:
            return ''

    def get_companyuser_nickname(self, obj):
        try:
            return obj.companyuser.nickname
        except:
            return ''


class CashActivityLevelStatisticalModelSerializer(serializers.ModelSerializer):

    child_list = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    level_type = serializers.SerializerMethodField(read_only=True)
    amountData = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivityLevel
        fields = ['level_name', 'level_type', 'p_max_amount', 'p_take_amount', 'p_remain_amount', 'amountData', 'child_list']

    def get_level_name(self, obj):
        return obj.level.name

    def get_level_type(self, obj):
        level = obj.level.level
        if level == 1:
            return '省公司'
        elif level == 2:
            return '市公司'
        elif level == 3:
            return '区县'
        elif level == 4:
            return '网点'
        else:
            return '信翔'

    def get_amountData(self, obj):
        data = [
            {"name": "已派发", "value": obj.p_take_amount},
            {"name": "剩余额度", "value": obj.p_remain_amount},
            {"name": "总额度", "value": obj.p_max_amount}
        ]
        return data

    def get_child_list(self, obj):
        level = obj.level
        if level.level == 1:
            list_queryset = CashActivityLevel.objects.filter(child_set__parent_id=obj.id, level__level=2)
            return CashActivityLevelStatisticalModelSerializer(list_queryset, many=True).data
        elif level.level == 2:
            list_queryset = CashActivityLevel.objects.filter(child_set__parent_id=obj.id, level__level=3)
            return CashActivityLevelStatisticalModelSerializer(list_queryset, many=True).data
        elif level.level == 3:
            list_queryset = CashActivityLevel.objects.filter(child_set__parent_id=obj.id, level__level=4)
            return CashActivityLevelStatisticalModelSerializer(list_queryset, many=True).data
        elif level.level == 4:
            return []
        else:
            return []


class CashActivityLevelTreeModelSerializer(serializers.ModelSerializer):

    level_type = serializers.SerializerMethodField(read_only=True)
    level_name = serializers.SerializerMethodField(read_only=True)
    p_unclaimed_amount = serializers.SerializerMethodField(read_only=True)
    activity_name = serializers.SerializerMethodField(read_only=True)
    is_auth_str = serializers.CharField(source='get_is_auth_display', read_only=True)
    child_list = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivityLevel
        fields = ['id', 'level_type', 'level_name', 'remain_amount', 'activity_name',
                  'p_receive_amount', 'p_remain_amount', 'p_take_amount', 'p_max_amount', 'p_unclaimed_amount', 'is_auth', 'is_auth_str',
                  'child_list']

    def get_p_unclaimed_amount(self, obj):
        try:
            p_unclaimed_amount = obj.p_take_amount - obj.p_receive_amount
            return p_unclaimed_amount
        except:
            return ''

    def get_activity_name(self, obj):
        try:
            return obj.cash_activity.name
        except:
            return ''

    def get_level_name(self, obj):
        try:
            return obj.level.name
        except:
            return ''

    def get_level_type(self, obj):
        try:
            level = obj.level.level
            if level == 1:
                return '省公司'
            elif level == 2:
                return '市公司'
            elif level == 3:
                return '区县'
            elif level == 4:
                return  '网点'
            else:
                return '信翔'
        except:
            return ''

    def get_child_list(self, obj):
        level = obj.level
        if level.level == 1:
            list_queryset = CashActivityLevel.objects.filter(child_set__parent_id=obj.id, level__level=2)
            return CashActivityLevelTreeModelSerializer(list_queryset, many=True).data
        elif level.level == 2:
            list_queryset = CashActivityLevel.objects.filter(child_set__parent_id=obj.id, level__level=3)
            return CashActivityLevelTreeModelSerializer(list_queryset, many=True).data
        elif level.level == 3:
            list_queryset = CashActivityLevel.objects.filter(child_set__parent_id=obj.id, level__level=4)
            return CashActivityLevelTreeModelSerializer(list_queryset, many=True).data
        elif level.level == 4:
            return []
        else:
            return []


class CashActivityLevelRecordModelSerializer(serializers.ModelSerializer):

    level_name = serializers.SerializerMethodField(read_only=True)
    operation_type_str = serializers.CharField(source='get_operation_type_display', read_only=True)
    activity_type_str = serializers.CharField(source='get_activity_type_display', read_only=True)
    user_nickname = serializers.SerializerMethodField(read_only=True)
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)

    class Meta:
        model = CashActivityLevelRecord
        fields = ['id', 'level_name', 'operation_type', 'operation_type_str', 'amount', 'remain_amount', 'create_time', 'remark', 'user_nickname', 'activity_type', 'activity_type_str']

    def get_level_name(self, obj):
        try:
            return obj.activity_level.level.name
        except:
            return ''

    # def get_amount(self, obj):
    #     try:
    #         if obj.operation_type in [1, 3, 6]:
    #             return obj.amount
    #         else:
    #             return -obj.amount
    #     except:
    #         return ''

    def get_user_nickname(self, obj):
        try:
            return obj.user.nickname
        except:
            return ''


class CashActivityWhiteTableModelSerializer(serializers.ModelSerializer):

    add_user = serializers.SerializerMethodField(read_only=True)
    merchant = serializers.SerializerMethodField(read_only=True)
    add_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)

    class Meta:
        model = CashActivityWhiteTable
        fields = ('id', 'mobile', 'add_user', 'add_time', 'business_no', 'contact_name', 'id_card_number', 'is_admin', 'merchant')

    def get_add_user(self, obj):
        try:
            return obj.add_user.nickname
        except:
            return ''

    def get_merchant(self, obj):
        data = {}
        data['merchant_name'] = ''
        data['level_name'] = ''
        data['managermobile'] = ''
        data['managerName'] = ''
        try:
            merchant = Merchant.objects.filter(wyfMerchantID=obj.business_no).first()
            if merchant:
                data['managermobile'] = merchant.managermobile
                data['managerName'] = merchant.managerName
                data['merchant_name'] = merchant.name
                data['level_name'] = merchant.level.name
        except:
            pass
        return data


class CashActivityDataKeguanListModelSerializer(serializers.ModelSerializer):

    push_status_str = serializers.CharField(source='get_push_status_display', read_only=True)
    push_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    payment_no = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CashActivityDataKeguan
        fields = ['id', 'push_status_str', 'push_status', 'push_time', 'return_msg', 'cashactivitydata_id', 'payment_no']

    def get_payment_no(self, obj):
        try:
            return obj.cashactivitydata.payment_no
        except:
            return ''